package com.dayuanit.dy17.atm.atmbackoffice.service.impl;

import com.alibaba.excel.EasyExcel;
import com.dayuanit.dy17.atm.atmbackoffice.dto.SalaryDTO;
import com.dayuanit.dy17.atm.atmbackoffice.dto.SalaryDetailDTO;
import com.dayuanit.dy17.atm.atmbackoffice.entity.Card;
import com.dayuanit.dy17.atm.atmbackoffice.entity.Flow;
import com.dayuanit.dy17.atm.atmbackoffice.entity.Salary;
import com.dayuanit.dy17.atm.atmbackoffice.entity.SalaryDetail;
import com.dayuanit.dy17.atm.atmbackoffice.enums.FlowTypeEnum;
import com.dayuanit.dy17.atm.atmbackoffice.enums.SalaryStatusEnum;
import com.dayuanit.dy17.atm.atmbackoffice.excel.SalaryData;
import com.dayuanit.dy17.atm.atmbackoffice.excel.SalaryDataListener;
import com.dayuanit.dy17.atm.atmbackoffice.exception.BizException;
import com.dayuanit.dy17.atm.atmbackoffice.mapper.CardMapper;
import com.dayuanit.dy17.atm.atmbackoffice.mapper.FlowMapper;
import com.dayuanit.dy17.atm.atmbackoffice.mapper.SalaryDetailMapper;
import com.dayuanit.dy17.atm.atmbackoffice.mapper.SalaryMapper;
import com.dayuanit.dy17.atm.atmbackoffice.service.ISalaryService;
import com.dayuanit.dy17.atm.atmbackoffice.util.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class SalaryServiceImpl implements ISalaryService {

    @Autowired
    private SalaryMapper salaryMapper;

    @Autowired
    private SalaryDetailMapper salaryDetailMapper;

    @Autowired
    private CardMapper cardMapper;

    @Autowired
    private FlowMapper flowMapper;


    @Override
    @Transactional
    public void createSalaryOrder(long uploadUserId, String salaryFileName, String remark) {
        if (StringUtils.isBlank(remark)) {
            throw new BizException("请输入备注");
        }

        //工资单主表
        Salary salary = new Salary();
        salary.setCreateTime(new Date());
        salary.setModifyTime(salary.getCreateTime());
        salary.setRemark(remark);
        salary.setSalaryFileName(salaryFileName);
        salary.setStatus(1);
        salary.setUserId(uploadUserId);
        salaryMapper.insert(salary);

        //TODO 处理工资单

        String fileName = "D:/dayuanit/17/tmp/" + salaryFileName;
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, SalaryData.class, new SalaryDataListener(this, salary.getId())).sheet().doRead();
    }

    @Override
    public List<SalaryDTO> loadSalaryOrder() {
        List<Salary> salaries = salaryMapper.listSalary(null);
        List<SalaryDTO> dtos = new ArrayList<>(salaries.size());

        for (Salary salary : salaries) {
            SalaryDTO salaryDTO = new SalaryDTO();
            dtos.add(salaryDTO);

            salaryDTO.setCreateTime(DateUtils.date2String(salary.getCreateTime()));
            salaryDTO.setRemark(salary.getRemark());
            salaryDTO.setSalaryId(salary.getId());
            salaryDTO.setStatus(salary.getStatus());
        }
        return dtos;
    }

    @Override
    public void saveSalaryDetail(long salaryId, List<SalaryData> salaryDatas) {
        if (salaryDatas.isEmpty()) {
            return;
        }

        List<SalaryDetail> details = new ArrayList<>(salaryDatas.size());

        for (SalaryData salaryData : salaryDatas) {
            SalaryDetail salaryDetail = new SalaryDetail();

            salaryDetail.setAmount(salaryData.getAmount());
            salaryDetail.setCardNum(salaryData.getCardNum());
            salaryDetail.setSalaryId(salaryId);

            details.add(salaryDetail);
        }

        salaryDetailMapper.insertSalaryDetails(details);
    }

    @Override
    public List<SalaryDetailDTO> querySalaryDetail(long salaryId) {
        List<SalaryDetail> details = salaryDetailMapper.listBySalaryId(salaryId);
        List<SalaryDetailDTO> dtos = new ArrayList<>(details.size());

        for (SalaryDetail salaryDetail : details) {
            SalaryDetailDTO salaryDetailDTO = new SalaryDetailDTO();
            dtos.add(salaryDetailDTO);

            salaryDetailDTO.setAmount(salaryDetail.getAmount().toString());
            salaryDetailDTO.setCardNum(salaryDetail.getCardNum());
            salaryDetailDTO.setId(salaryDetail.getId());
        }
        return dtos;
    }

    @Transactional
    @Override
    public void approval(long salaryId, int approvalStatus) {
        Salary salary = salaryMapper.selectByPrimaryKey(salaryId);

        if (null == salary) {
            throw new BizException("工资单不存在");
        }

        int rows = 0;
        // 如果同意 如何处理
        if (approvalStatus == SalaryStatusEnum.success_approval.getK()) {
            //判断订单的目前状态
            if (salary.getStatus() == SalaryStatusEnum.wait_approval.getK()
                    || salary.getStatus() == SalaryStatusEnum.fail_approval.getK()) {
                rows = salaryMapper.updateStatus(salary.getStatus(), salaryId, approvalStatus);

                //TODO 加钱 我用定时器去加钱
            }
        }

        // 不同意 如何处理
        if (approvalStatus == SalaryStatusEnum.fail_approval.getK()) {
            if (salary.getStatus() == SalaryStatusEnum.wait_approval.getK()) {
                rows = salaryMapper.updateStatus(salary.getStatus(), salaryId, approvalStatus);
            }
        }

        if (1 != rows) {
            throw new BizException("审批失败");
        }

    }

    @Transactional
    @Override
    public void payOff(Salary salary) {
        //TODO 修改工资单状态
        int rows = salaryMapper.updateStatus(salary.getStatus(), salary.getId(), SalaryStatusEnum.salary_approval.getK());
        if (1 != rows) {
            throw new BizException("发放失败");
        }

        //加载明细
        //方案一：所有当前工资单的银行卡一块处理，如果有一个失败，全部失败
        //方案二：允许部分银行卡失败，不影响其他银行卡的加钱，则需要在salaryDetail表增加状态(1-待付款 2-已付款)，开个定时器扫描即可。
        List<SalaryDetail> details = salaryDetailMapper.listBySalaryId(salary.getId());
        for (SalaryDetail salaryDetail : details) {
            payCard(salaryDetail);
        }
    }

    // 给每个银行卡加钱
    private void payCard(SalaryDetail salaryDetail) {
        Card card = cardMapper.getByCardNum(salaryDetail.getCardNum());

        int amount = salaryDetail.getAmount().multiply(new BigDecimal(100)).intValue();
        int newBalance = card.getBalance() + amount;
        int rows = cardMapper.updateBalance(card.getId(), card.getBalance(), newBalance);
        if (1 != rows) {
            throw new BizException("加钱失败");
        }

        Flow flow = new Flow();
        flow.setAmount(amount);
        flow.setCardId(card.getId());
        flow.setCreateTime(new Date());
        flow.setFlowType(FlowTypeEnum.salary.getK());
        flow.setRemark("发工资");
        flow.setUserId(card.getUserId());
        rows = flowMapper.insert(flow);
        if (1 != rows) {
            throw new BizException("加钱失败");
        }
    }
}
